package com.leetcode.leetcode1;

/**
 * @program: 无重复字符的最长子串
 * @author: luhd
 * @create: 2021-08-13
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
 *  给定一个字符串 s ，请你找出其中不含有重复字符的 最长子串 的长度。
 *
 *  示例 1:
 * 输入: s = "abcabcbb"
 * 输出: 3
 * 解释: 因为无重复字符的最长子串是 "abc"，所以其长度为 3
 */
public class practice03 {
    public static void main(String[] args) {
        Solution solution = new Solution();
        solution.lengthOfLongestSubstring("pwwkew");
    }
/*    static class Solution {
        public int lengthOfLongestSubstring(String s) {
            int len = s.length();
            int maxLength = 0;
            ArrayList<Character> al = new ArrayList<>();
            for (int i = 0; i < len; i++) {
                for (int j = i; j < len; j++) {
                    if(al.contains(s.charAt(j))){
                        break;
                    }
                    al.add(s.charAt(j));
                    maxLength = maxLength > al.size() ? maxLength : al.size();

                }
                al.clear();
            }
            System.out.println(maxLength);
            //for (int i = 0; i < al.size(); i++) {
            //    System.out.println(al.get(i));
            //}
            return maxLength;
        }
    }*/
    //改进
    static class Solution {
        public int lengthOfLongestSubstring(String s) {
            // 哈希集合，记录每个字符是否出现过
            Set<Character> occ = new HashSet<Character>();
            int n = s.length();
            // 右指针，初始值为 -1，相当于我们在字符串的左边界的左侧，还没有开始移动
            int rk = -1, ans = 0;
            for (int i = 0; i < n; ++i) {
                /**
                 *  灵魂所在，当不满足条件的时候，左指针前移，缩小窗口
                 */
                if (i != 0) {
                    // 左指针向右移动一格，移除一个字符
                    occ.remove(s.charAt(i - 1));
                }
                /**
                 *  右指针和i解耦，不受循环影响，，即当不符合条件的时候，右指针指向的位置不变，做左指针前移，直到符合条件
                 */
                while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
                    // 不断地移动右指针
                    occ.add(s.charAt(rk + 1));
                    ++rk;
                }
                // 第 i 到 rk 个字符是一个极长的无重复字符子串
                /**
                 * 每次条件被破坏的时候，即有重复元素的时候，对窗口的大小重新赋值
                 */
                ans = Math.max(ans, rk - i + 1);
            }
            return ans;
        }
    }
}
